﻿using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using Aliyun.OSS;
using Aliyun.OSS.Common;
using Aliyun.OSS.Model;
using Aliyun;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace Vav.Data.OSS
{
    public class OssContext
    {
        private readonly OssOptions ossOptions;
        private readonly OssClient ossClient;
        private JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings()
        {
            Converters = { new StringEnumConverter() }
        };

        public OssContext(OssOptions ossOptions)
        {
            this.ossOptions = ossOptions;
            ossClient = new OssClient(ossOptions.Endpoint, ossOptions.AccessKeyId, ossOptions.AccessKeySecret);
        }

        public string BucketName { get => ossOptions.BucketName; }

        public string GeneratePresignedUrl(string bucketName, string key)
        {
            return ossClient.GeneratePresignedUri(bucketName, key).AbsoluteUri;
        }
        
        public List<OssObjectSummary> SearchObjects(string bucketName, string prefix)
        {
            var listing = ossClient.ListObjects(new ListObjectsRequest(bucketName)
            {
                Prefix = prefix
            });
            return listing.ObjectSummaries.ToList();
        }

        public List<string> SearchDirectories(string bucketName, string prefix)
        {
            var listing = ossClient.ListObjects(new ListObjectsRequest(bucketName)
            {
                Prefix = prefix,
                Delimiter = "/"
            });
            return listing.CommonPrefixes.ToList();
        }

        public T ReadJsonObject<T>(string bucketName, string key) where T: new()
        {
            var obj = ossClient.GetObject(bucketName, key);
            using(var content = obj.Content)
            {
                using(StreamReader reader = new StreamReader(content, Encoding.UTF8))
                {
                    var json = reader.ReadToEnd();
                    return JsonConvert.DeserializeObject<T>(json, JsonSerializerSettings);
                }
            }
        }

        public void WriteJsonObject<T>(T obj, string bucketName, string key)
        {
            var json = JsonConvert.SerializeObject(obj, JsonSerializerSettings);
            using(MemoryStream jsonStream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
            {
                ossClient.PutObject(bucketName, key, jsonStream);
            }
        }

        public void DeleteObject(string bucketName, string key)
        {
            ossClient.DeleteObject(bucketName, key);
        }

        public void DeleteObjects(string bucketName, IEnumerable<string> keys)
        {
            ossClient.DeleteObjects(new DeleteObjectsRequest(bucketName, keys.ToList()));
        }
    }
}
